

/* 
1. 创建了一个全新的对象。
2. 这个对象会被执行[[Prototype]]（也就是__proto__）链接。
3. 生成的新对象会绑定到函数调用的this。
4. 通过new创建的每个对象将最终被[[Prototype]]链接到这个函数的prototype对象上。
5. 如果函数没有返回对象类型Object(包含Functoin, Array, Date, RegExg, Error)，那么new表达式中的函数调用会自动返回这个新的对象

*/

/* 
实现原理：
1. 首先函数接受不定量的参数，第一个参数为构造函数，接下来的参数被构造函数使用
2. 然后内部创建一个空对象obj
3. 因为obj对象需要访问到构造函数原型链上的属性，所以我们通过setProtoypeOf将两者联系起来。这段代码等同于obj.__proto__=Con.prototype
4. 将obj绑定到构造函数上，并且传入剩余的参数
5. 判断构造函数返回值是否为对象，如果为对象就使用构造函数返回的值，否则使用obj，这样就实现了忽略构造函数返回的原始值
*/

/* 
Object.setPrototypeOf(obj, prototype)
1. 不推荐使用setPrototypeOf，更改一个对象的__proto__在js上性能开销太大
2. 推荐使用Object.create(),直接在创建的时候指定对象的__proto__
*/

/* 
funciton fn(Con, ...args) 
这样写会将第二个参数开始的之后的参数以数组的形式存放在args中
*/

function create(Con, ...args) {
    // let obj = {}
    // Object.setPrototypeOf(obj, Con.prototype)
    let obj = Object.create(Con.prototype)
    let result = Con.apply(obj, args)
    // let result = Con()
    // console.log('1', result instanceof Object)
    return result instanceof Object ? result : obj
}

function Test(name, age) {
    this.name = name
    this.age = age
    return [1, 2, 3]
}
Test.prototype.sayName = function () {
    console.log(this.name)
}

const a = create(Test, 'yck', 26)
console.log(a);
// console.log(a.name) // 'yck'
// console.log(a.age) // 26
// a.sayName() // 'yck'